package game.editer;

import game.editer.ui.LabelListView;
import haxe.Timer;
import game.editer.history.RemoveFrame;
import game.editer.history.AddFrame;
import game.editer.ui.Button;
import game.data.ITimelineData;
import game.worlds.GameEffect;
import game.data.EffectData;
import game.editer.config.ActionDataConfig;
import game.editer.view.InputListDataView;
import game.editer.view.AlertView;
import hx.display.VBox;
import game.data.FrameData;
import game.editer.ui.CommonButton;
import hx.display.HBox;
import hx.events.Event;
import hx.events.MouseEvent;
import game.data.IRoleData;
import game.data.ProjectRoleData;
import game.editer.ui.Config;
import game.editer.ui.DownDropListView;
import hx.display.TextFormat;
import hx.display.Label;
import hx.display.Quad;
import game.data.ActionData;
import openfl.display.Timeline;
import hx.display.DisplayObjectRecycler;
import hx.display.ArrayCollection;
import hx.layout.AnchorLayoutData;
import hx.layout.AnchorLayout;
import hx.layout.HorizontalLayout;
import hx.display.ListView;
import hx.display.ItemRenderer;
import hx.display.Box;

/**
 * 时间戳编辑器
 */
class TimelineEditer extends BasePanel {
	public function new() {
		super("时间轴");
	}

	/**
	 * 项目数据
	 */
	public var projectData(default, set):IRoleData;

	/**
	 * 动作列表
	 */
	public var actionsListView(get, never):LabelListView;

	private function get_actionsListView():LabelListView {
		return EditerStage.actionPlane.actionsListView;
	}

	/**
	 * 时间轴列表
	 */
	public var timelineListView:ListView;

	/**
	 * 特效时间轴列表
	 */
	public var effectTimelineListView:ListView;

	/**
	 * 当前编辑的特效数据时间轴
	 */
	public var currentEffectData:EffectData;

	private var exitBtn:Button;

	/**
	 * 进入该特效的时间轴中
	 * @param effectData 
	 */
	public function showEffectDataTimeline(effectData:EffectData):Void {
		this.exitBtn.visible = effectData != null;
		this.currentEffectData = effectData;
		this.timelineListView.visible = effectData == null;
		this.effectTimelineListView.visible = effectData != null;
		if (this.effectTimelineListView.visible) {
			var atlas = EditerStage.roleAssets.getAtlas(effectData.name);
			var bitmaps = atlas.getBitmapDatasByName("");
			if (effectData.frames.length != bitmaps.length) {
				// 初始化时间轴
				for (i in 0...bitmaps.length) {
					var frame = effectData.frames[i] ?? new FrameData();
					frame.frame = i;
					effectData.addFrame(frame);
				}
				effectData.frames.splice(bitmaps.length, effectData.frames.length - bitmaps.length);
				effectData.updateActionData();
			}
			this.effectTimelineListView.data = new ArrayCollection([
				for (i => data in effectData.frames) {
					{
						frame: i,
						data: data
					}
				}
			]);
		} else {
			this.currentFrame = this.currentFrame;
		}
		this.updateTimelineData(true);
	}

	/**
	 * 当前帧数据
	 */
	public var currentFrameData(get, never):FrameData;

	private function get_currentFrameData():FrameData {
		if (this.timelineListView.visible
			&& this.currentActionData != null
			&& this.currentFrame >= 0
			&& this.currentFrame < this.currentActionData.frames.length) {
			return this.currentActionData.frames[this.currentFrame];
		} else if (this.effectTimelineListView.visible && this.effectTimelineListView.selectedItem != null) {
			return this.effectTimelineListView.selectedItem.data;
		}
		return null;
	}

	/**
	 * 当前帧
	 */
	public var currentFrame(get, set):Int;

	private var __ignoreEvent:Bool = false;

	private function set_currentFrame(value:Int):Int {
		if (this.currentActionData != null) {
			if (value < 0) {
				value = this.currentActionData.frames.length - 1;
			} else if (value >= this.currentActionData.frames.length) {
				value = 0;
			}
		}
		this.timelineListView.selectedIndex = value;
		var eff = getCurrentTimeLineEffect();
		if (eff != null) {
			// this.effectTimelineListView.selectedIndex = eff.currentFrameData.frame;
		} else {
			this.effectTimelineListView.selectedIndex = -1;
		}
		EditerStage.objectSelect.update();
		return value;
	}

	/**
	 * 最大帧数
	 */
	public var maxFrame(get, never):Int;

	private function get_maxFrame():Int {
		if (this.currentActionData != null) {
			return this.currentActionData.frames.length;
		}
		return 0;
	}

	private function get_currentFrame():Int {
		return this.timelineListView.selectedIndex;
	}

	/**
	 * 获得当前动作数据
	 */
	public var currentActionData(get, never):ActionData;

	private function get_currentActionData():ActionData {
		if (this.actionsListView.selectedItem != null) {
			var actionData:ActionData = cast this.actionsListView.selectedItem.data;
			return actionData;
		}
		return null;
	}

	private function set_projectData(value:IRoleData):IRoleData {
		this.projectData = value;
		if (!actionsListView.hasEventListener(Event.CHANGE))
			actionsListView.addEventListener(Event.CHANGE, onDownlistViewChange);
		if (value != null) {
			actionsListView.data = new ArrayCollection([
				for (action in value.actions) {
					{
						text: action.name + "(" + action.getGroupsKeyString() + ")",
						data: action
					};
				}
			]);
		}
		return value;
	}

	/**
	 * 是否正在预览动画
	 */
	public var isPreview:Bool = false;

	public var isLoop:Bool = false;

	public var playAndPauseBtn:CommonButton;

	override function onInit() {
		super.onInit();

		this.height = 36 + (26 + 1) * LabelsTip.labels.length + 2 + 16;

		var timeBg = new Quad(1, 1, 0x2e2e2e);
		this.addChild(timeBg);
		timeBg.layoutData = new AnchorLayoutData(36, 1, 1, 1);

		// 时间轴按钮
		var hbox = new HBox();
		hbox.gap = 5;
		this.addChild(hbox);
		hbox.y = 9;
		hbox.x = label.getTextWidth() + 20;

		// 播放和暂停按钮
		playAndPauseBtn = new CommonButton("UIAtlas:play");
		hbox.addChild(playAndPauseBtn);
		playAndPauseBtn.addEventListener(MouseEvent.CLICK, (e) -> {
			if (EditerStage.world.role == null) {
				return;
			}
			if (currentActionData == null)
				return;
			if (!EditerStage.world.role.isPlaying) {
				isPreview = true;
				playAndPauseBtn.setImage("UIAtlas:pause");
				@:privateAccess EditerStage.world.role.__currentSkillActionName = this.currentActionData.name;
				if (EditerStage.world.role.currentFrame == this.currentActionData.frames.length - 1) {
					EditerStage.world.role.x = EditerStage.world.role.y = 0;
					EditerStage.world.role.playAndStop(this.currentActionData.name, 0);
				}
				if (@:privateAccess EditerStage.world.role.__movieClip != null) {
					// @:privateAccess EditerStage.world.role.__movieClip.reset();
					@:privateAccess EditerStage.world.role.__movieClip.play();
				}
			} else {
				isPreview = false;
				playAndPauseBtn.setImage("UIAtlas:play");
				@:privateAccess EditerStage.world.role.__currentSkillActionName = null;
				if (@:privateAccess EditerStage.world.role.__movieClip != null)
					@:privateAccess EditerStage.world.role.__movieClip.pause();
			}
		});

		//
		var loopBtn = new CommonButton("UIAtlas:loop");
		hbox.addChild(loopBtn);
		loopBtn.addEventListener(MouseEvent.CLICK, (e) -> {
			isLoop = !isLoop;
			loopBtn.quad.data = isLoop ? 0x2a86bf : 0x666666;
			loopBtn.upColor = isLoop ? 0x2a86bf : 0x666666;
		});

		// 退出特效时间轴按钮
		exitBtn = new Button();
		exitBtn.text = "返回原时间轴";
		exitBtn.y = -6;
		hbox.addChild(exitBtn);
		exitBtn.addEventListener(MouseEvent.CLICK, (e) -> {
			this.showEffectDataTimeline(null);
		});
		exitBtn.visible = false;

		var labels = new LabelsTip();
		this.addChild(labels);
		labels.layoutData = new AnchorLayoutData(36, 0, 0, 0);

		var list = new ListView();
		list.layout = new HorizontalLayout();
		cast(list.layout, HorizontalLayout).gap = 0;
		this.addChild(list);
		this.layout = new AnchorLayout();
		list.layoutData = new AnchorLayoutData(37, 4, 4, 1 + 140);
		list.itemRendererRecycler = DisplayObjectRecycler.withClass(TimelineFrame);
		list.data = new ArrayCollection([]);
		list.scrollYEnable = false;
		this.timelineListView = list;
		this.timelineListView.addEventListener(Event.CHANGE, onTimelineChange);

		var list = new ListView();
		list.layout = new HorizontalLayout();
		cast(list.layout, HorizontalLayout).gap = 0;
		this.addChild(list);
		this.layout = new AnchorLayout();
		list.layoutData = new AnchorLayoutData(37, 4, 4, 1 + 140);
		list.itemRendererRecycler = DisplayObjectRecycler.withClass(TimelineFrame);
		list.data = new ArrayCollection([]);
		list.scrollYEnable = false;
		this.effectTimelineListView = list;
		this.effectTimelineListView.visible = false;
		this.effectTimelineListView.addEventListener(Event.CHANGE, onEffectTimelineChange);

		// 时间轴滑动条
		var timelineMoveQuad = new Quad(1, 16, 0xff0000);
		this.addChild(timelineMoveQuad);
		timelineMoveQuad.layoutData = new AnchorLayoutData(37, 0, null, 140);
		timelineMoveQuad.alpha = 0;
		timelineMoveQuad.addEventListener(MouseEvent.MOUSE_DOWN, onTimelineMoveMouseEvent);

		this.updateEnabled = true;
	}

	/**
	 * 删除动作数据
	 * @param actionData 
	 */
	public function removeActionData(actionData:ActionData):Void {
		this.projectData.actions.remove(actionData.name);
		for (value in this.actionsListView.data.source) {
			if (value.data.name == actionData.name) {
				this.actionsListView.data.remove(value);
				break;
			}
		}
		this.actionsListView.selectedIndex = 0;
	}

	/**
	 * 添加动作数据
	 * @param actionData 
	 */
	public function addActionData(actionData:ActionData):Void {
		if (!this.projectData.actions.exists(actionData.name)) {
			this.projectData.actions.set(actionData.name, actionData);
			this.actionsListView.data.add({
				text: actionData.name + "(" + actionData.getGroupsKeyString() + ")",
				data: actionData
			});
			this.actionsListView.selectedIndex = this.actionsListView.data.length - 1;
			this.updateTimelineData();
		}
	}

	/**
	 * 插入帧
	 * @param frame 
	 */
	public function insertFrame(frame:FrameData):Void {
		if (this.currentActionData == null || !this.timelineListView.visible)
			return;

		var currentFrame = this.currentFrame;
		this.currentActionData.frames.insert(this.currentFrame + 1, frame);
		this.currentActionData.updateActionData();
		this.updateTimelineData(true);
		EditerStage.world.role.updateMovieClipActionData(this.currentActionData.name);
		EditerStage.world.role.playAndStop(this.currentActionData.name, currentFrame + 1);
		this.timelineListView.selectedIndex = Std.int(Math.min(this.currentActionData.frames.length - 1, currentFrame + 1));
		EditerStage.historyData.todo(new AddFrame(frame));
	}

	/**
	 * 删除帧
	 * @param frame 
	 */
	public function removeFrame(frame:FrameData):Void {
		if (this.currentActionData == null || !this.timelineListView.visible)
			return;

		var cur = this.currentFrame;
		currentActionData.frames.splice(frame.frame, 1);
		currentActionData.updateActionData();
		this.updateTimelineData();
		cur = Std.int(Math.min(this.currentActionData.frames.length, cur));
		EditerStage.world.role.updateMovieClipActionData(this.currentActionData.name);
		this.currentFrame = cur;

		EditerStage.historyData.todo(new RemoveFrame(frame));
	}

	/**
	 * 取消帧选中状态
	 */
	public function cannelFrameSelect():Void {
		var display:TimelineFrame = cast timelineListView.getChildAt(timelineListView.selectedIndex);
		if (display != null) {
			display.quad.colorTransform = null;
			for (quad in display.otherFrames) {
				quad.colorTransform = null;
			}
		}
	}

	override function onUpdate(dt:Float) {
		super.onUpdate(dt);
		if (EditerStage.world.role == null) {
			return;
		}
		if (EditerStage.world.role.isPlaying) {
			this.timelineListView.selectedIndex = EditerStage.world.role.currentFrame;
			if (currentActionData != null) {
				if (EditerStage.world.role.currentFrame == this.currentActionData.frames.length - 1) {
					if (isLoop) {
						@:privateAccess EditerStage.world.role.__movieClip.reset();
						EditerStage.world.role.x = 0;
						EditerStage.world.role.y = 0;
						EditerStage.world.role.playAndStop(this.currentActionData.name, 0);
						if (@:privateAccess EditerStage.world.role.__movieClip != null) {
							@:privateAccess EditerStage.world.role.__movieClip.reset();
							@:privateAccess EditerStage.world.role.__movieClip.play();
						}
						if (currentActionData != null)
							@:privateAccess EditerStage.world.role.__currentSkillActionName = this.currentActionData.name;
					} else {
						if (currentActionData != null)
							@:privateAccess EditerStage.world.role.__movieClip.pause();
						isPreview = false;
						playAndPauseBtn.setImage("UIAtlas:play");
					}
				}
			}
		}
	}

	override function onAddToStage() {
		super.onAddToStage();
		stage.addEventListener(MouseEvent.MOUSE_MOVE, onTimelineMoveMouseEvent);
		stage.addEventListener(MouseEvent.MOUSE_UP, onTimelineMoveMouseEvent);
	}

	override function onRemoveToStage() {
		super.onRemoveToStage();
		stage.removeEventListener(MouseEvent.MOUSE_MOVE, onTimelineMoveMouseEvent);
		stage.removeEventListener(MouseEvent.MOUSE_UP, onTimelineMoveMouseEvent);
	}

	private var __isMoveDown = false;

	private function updateTimelineMoveIndex(stageX:Float):Void {
		var index = Math.floor(stageX / 14);
		if (index < 0) {
			index = 0;
		} else if (index >= this.maxFrame) {
			index = this.maxFrame - 1;
		}
		if (this.timelineListView.visible) {
			this.currentFrame = index;
		} else {
			// 当前动作的FPS
			var currentFrame = getCurrentEffectFrame(index);
			this.currentFrame = currentFrame;
			this.effectTimelineListView.selectedIndex = index;
		}
	}

	private function onTimelineMoveMouseEvent(e:MouseEvent):Void {
		switch (e.type) {
			case MouseEvent.MOUSE_DOWN:
				__isMoveDown = true;
				updateTimelineMoveIndex(e.stageX - 140);
			case MouseEvent.MOUSE_MOVE:
				if (__isMoveDown) {
					this.updateTimelineMoveIndex(e.stageX - 140);
				}
			case MouseEvent.MOUSE_UP:
				__isMoveDown = false;
		}
	}

	private function onTimelineChange(e:Event):Void {
		// if (__ignoreEvent)
		// return;
		this.dispatchEvent(new Event(Event.CHANGE));
		EditerStage.objectSelect.update();
	}

	/**
	 * 获得当前特效时间轴的显示对象
	 * @return GameEffect
	 */
	public function getCurrentTimeLineEffect():GameEffect {
		for (object in EditerStage.world.displayBox.children) {
			if (object is GameEffect) {
				var eff:GameEffect = cast object;
				if (eff.originData == this.currentEffectData) {
					return eff;
				}
			}
		}
		return null;
	}

	public function getCurrentEffectFrame(index:Int):Int {
		// 当前动作的FPS
		var parentFrame = 0;
		var parent:EffectData = currentEffectData;
		while (parent != null && parent.frameData != null) {
			parentFrame += parent.frameData.frame;
			if (parent.frameData.timeline is EffectData) {
				var effectData:EffectData = cast parent.frameData.timeline;
				parent = effectData;
			} else {
				parent = null;
			}
		}
		var currentFPS = 1 / currentActionData.fps;
		var effectMaxFPS = 1 / currentEffectData.fps * index;
		var addFrame = Math.floor(effectMaxFPS / currentFPS);

		trace(parentFrame, addFrame, parentFrame + addFrame);

		return parentFrame + addFrame;
	}

	private function onEffectTimelineChange(e:Event):Void {
		if (__ignoreEvent)
			return;
		__ignoreEvent = true;
		if (this.effectTimelineListView.visible) {
			var currentFrame = getCurrentEffectFrame(this.effectTimelineListView.selectedIndex);
			this.currentFrame = currentFrame;
			// this.currentFrame = this.currentEffectData.frameData.frame + addFrame;
		}
		__ignoreEvent = false;
		// this.dispatchEvent(new Event(Event.CHANGE));
		// EditerStage.objectSelect.update();
	}

	/**
	 * 动作改变事件
	 * @param e 
	 */
	private function onDownlistViewChange(e:Event):Void {
		updateTimelineData();
	}

	public function updateTimelineData(keepFrame:Bool = false):Void {
		if (this.actionsListView.selectedItem != null) {
			var actionData:ActionData = cast this.actionsListView.selectedItem.data;
			this.timelineListView.data = new ArrayCollection([
				for (i => frame in actionData.frames) {
					{
						frame: i,
						data: frame
					};
				}
			]);
			if (EditerStage.world.role.isPlaying) {
				EditerStage.world.role.playSkill(actionData.name);
			}
			if (!keepFrame)
				this.currentFrame = 0;
			this.dispatchEvent(new Event(Event.CHANGE));
		}
	}

	/**
	 * 动作数据
	 */
	public var actionData(default, set):ActionData;

	private function set_actionData(value:ActionData):ActionData {
		this.actionData = value;
		return value;
	}

	/**
	 * 下一帧
	 */
	public function nextFrame():Void {
		if (this.currentActionData != null) {
			this.currentFrame++;
			this.dispatchEvent(new Event(Event.CHANGE));
		}
	}

	/**
	 * 上一帧
	 */
	public function prevFrame():Void {
		if (this.currentActionData != null) {
			this.currentFrame--;
			this.dispatchEvent(new Event(Event.CHANGE));
		}
	}
}

/**
 * 时间轴文本提示组件
 */
class LabelsTip extends VBox {
	public static var labels = ["帧", "特效", "停顿", "位移", "缩放", "旋转", "透明", "事件", "音频", "碰撞"];

	override function onInit() {
		super.onInit();
		for (index => text in labels) {
			var box = new Box();
			box.width = this.width;
			box.height = index == 0 ? 42 : 26;
			box.layout = new AnchorLayout();
			var label = new Label(text, Config.COMMON_TEXT_FORMAT);
			label.width = 140;
			label.horizontalAlign = CENTER;
			label.layoutData = new AnchorLayoutData(null, null, null, null, null, 0);
			var quad = new Quad(140, 1, 0x4b4b4b);
			this.addChild(box);
			box.addChild(quad);
			box.addChild(label);
			quad.layoutData = new AnchorLayoutData(0, null, 0, null);

			var lineQuad = new Quad(1, 1, 0x202020);
			box.addChild(lineQuad);
			lineQuad.layoutData = new AnchorLayoutData(0, 0, 0, 140);
		}
		this.gap = 1;
	}
}
